热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

也就是|左上角_AbstractProcessor相关的API记录

本文由编程笔记#小编为大家整理,主要介绍了AbstractProcessor相关的API记录相关的知识,希望对你有一定的参考价值。java文件操作相关的两个类:
本文由编程笔记#小编为大家整理,主要介绍了AbstractProcessor相关的API记录相关的知识,希望对你有一定的参考价值。


java文件操作相关的两个类: JCTree 树节点、TreeMaker 树节点构建器。



JCTree

JCTree的一个子类就是java语法中的一个节点,类、方法、字段等这些都被封装成了一个JCTree子类。

JCTree详细的介绍:抽象语法树AST的全面解析(二) - 简书


TreeMaker

TreeMaker 里的方法用于构建JCTree某个子类,例:treeMaker.MethodDef(…)返回值是JCTree的子类JCMethodDecl(方法节点)

TreeMaker创建各种节点的方法如下:

// public访问修饰符
JCTree.JCModifiers publicDot = treeMaker.Modifiers(Flags.PUBLIC);
// void关键字
JCTree.JCPrimitiveTypeTree voidDot = treeMaker.TypeIdent(TypeTag.VOID);
// 空语句
JCTree.JCBlock emptyDot = treeMaker.Block(0, List.nil());
// 一个无参构造方法
JCTree.JCMethodDecl noArgsMethod = treeMaker.MethodDef(
publicDot,
names.fromString(""),
voidDot ,
List.nil(),
List.nil(),
List.nil(),
emptyDot,
null);
// this关键字
JCTree.JCIdent thisDot = treeMaker.Ident(names.fromString("this"));
// userPassword (Name类型可以是方法名、字段名、变量名、类名)
Name userPasswordName = names.fromString("userPassword");
// this.userPassword (访问当前方法中的字段userPassword)
JCTree.JCFieldAccess thisUserPassword = treeMaker.Select(thisDot , userPasswordName);
// userPassword 变量
JCTree.JCIdent userPassword = treeMaker.Ident(userPasswordName);
// this.userPassword = userPassword (treeMaker.Apply()以及treeMaker.Assign()需要外面包一层treeMaker.Exec())
treeMaker.Exec(treeMaker.Assign(thisUserPassword, userPassword));

 如以下代码是给一个方法新增一句话System.out.println("hello world")

package jst;
import com.google.auto.service.AutoService;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.util.Set;
/**
* @author wuweifeng wrote on 2022/12/21
* @version 1.0
*/
@SupportedAnnotationTypes("jst.HelloWorld")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor
@Override
public boolean process(Set annotations, RoundEnvironment roundEnv)
Set elements = roundEnv.getRootElements();
final Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
final JavacElements elementUtils = (JavacElements) processingEnv.getElementUtils();
final TreeMaker treeMaker = TreeMaker.instance(context);
for (Element element : roundEnv.getElementsAnnotatedWith(HelloWorld.class))
JCTree.JCMethodDecl jcMethodDecl = (JCTree.JCMethodDecl) elementUtils.getTree(element);
treeMaker.pos = jcMethodDecl.pos;
jcMethodDecl.body = treeMaker.Block(0, List.of(
treeMaker.Exec(
treeMaker.Apply(
List.nil(),
treeMaker.Select(
treeMaker.Select(
treeMaker.Ident(
elementUtils.getName("System")
),
elementUtils.getName("out")
),
elementUtils.getName("println")
),
List.of(
treeMaker.Literal("Hello, world!!!")
)
)
),
jcMethodDecl.body
));

return false;


使用时

@HelloWorld
public static void main(String[] args)
System.out.println("demo打印");

加上了@HelloWorld注解后,运行就会打印

现在针对MyProcessor类里的内容做个解释。

jcMethodDecl.body即为方法体,利用treemaker的Block方法获取到一个新方法体,将原来的替换掉。就达到了修改方法体的目的了。这里的Block方法有两个参数,重点要关注的是第二个参数,也就是具体的方法体内容。它是一个List类型的参数,List里面每一个元素就代表一个语句块,比如,例子中有两块语句,第一块是我们织入的代码块:System.out.println("Hello, world!!!");用treeMaker.Exec()来实现,第二块是原来的代码块:jcMethodDecl.body。这块的代码是用户原本的代码,我们直接放进来就行。这个List是有顺序的,谁的顺序在前,谁最终生成的代码块就在前,比如这里我们织入的代码在原来的代码块之前,所以最终生成System.out.println("Hello, world!!!");语句就在该方法的第一行位置。

重点关注的应该是treeMaker.Exec()这个方法,这个方法帮助我们最终生成了System.out.println("Hello, world!!!");这条语句,它的参数是treeMaker.Apply这个方法的返回结果,这个方法的第二个参数,也就是最终实现了输出System.out.println("Hello, world!!!")的东西。

这里面用到了两个方法,一个是treeMaker.Select(生成具体的方法),一个是treeMaker.Literal(方法的参数)。treeMaker.Select里面套了很多层,对比两种写法的区别,你也能明白,这是为了写出多级方法的做法,多级方法的第一级以treeMaker.Ident开始,然后一层套一层,直到整个方法结束。


如何debug processor代码

a)idea右上角,Edit Configurations

b)点击左上角的+号,选择Remote,或者如图的Remote JVM debug

 

c)随便起一个名字,比如ProcessorDebug,如图,点击确定。

d)进入Terminal界面,输入mvnDebug clean install,回车,不出意外的话,会出现如图的提示

f)process里面打上断点,然后点击debug按钮,便命中了断点

 


异常情况 

如果在rebuild project时出现:java: java.lang.ClassCastException: com.sun.proxy.$Proxy26 cannot be cast to com.sun.tools.javac.processing.JavacProcessingEnvironment

则在设置里添加如下内容:

-Djps.track.ap.dependencies=false

 


推荐阅读
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • vue使用
    关键词: ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
author-avatar
燕灬子78
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有